package com.LachesismStorm.lachesism.member.service.impl;

import com.LachesismStorm.lachesism.core.common.response.ResponsePage;
import com.LachesismStorm.lachesism.core.email.EmailUtil;
import com.LachesismStorm.lachesism.core.service.RedisService;
import com.LachesismStorm.lachesism.core.util.AsyncUtil;
import com.LachesismStorm.lachesism.core.util.LachesismTools;
import com.LachesismStorm.lachesism.member.dto.ConstellationDTO;
import com.LachesismStorm.lachesism.member.mapper.YunOMapper;
import com.LachesismStorm.lachesism.member.service.SchedulerService;
import com.LachesismStorm.lachesism.member.service.YunOService;
import com.LachesismStorm.lachesism.member.vo.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.SneakyThrows;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.LachesismStorm.lachesism.core.common.enums.CommonEnum.*;
import static com.LachesismStorm.lachesism.core.util.LachesismTools.*;
import static com.LachesismStorm.lachesism.member.util.ConstellationUtil.*;


/**
 * @Author lachesism
 * @Date 2024-04-10 16:07
 **/
@Service
public class YunOServiceImpl implements YunOService {
    @Resource
    private YunOMapper yunOMapper;
    @Value("${file.temp.address}")
    private String temp;
    @Value("${file.files.address}")
    private String fileAddress;
    @Resource
    private RedisService redisService;

    @Resource
    private SchedulerService schedulerService;
    @Resource
    private EmailUtil emailUtil;

    @PostConstruct
    public void init() {
        System.out.println("定时任务启动");
        // 启动定时任务
        schedulerService.startScheduledTasks(
                this::autoUpload,             // 每小时自动上传
                this::getDailyVideo,          // 每小时获取视频
                this::clearTempFiles,         // 每天清理临时文件
                this::getConstellationList,   // 每天获取星座信息
                this::addOldCalendar          // 每天添加旧日历
        );
    }


    public void autoUpload() {
//        emailUtil.sendMissEmail("qq", "2595647320@qq.com", "马来貘快看", "constellationTemplate/Miss.html", getTime(DATETIME_FORMATTER) + "，这一刻");
        System.out.println("================================================================" + "\n" + LachesismTools.getTime("yyyy年MM月dd日 HH时mm分ss秒") + "-  开始保存金价" + "\n");
        String price = getNewGoldPrice();
        redisService.set("goldPrice", price, 1);
        BigDecimal priceValue = new BigDecimal(price);
        yunOMapper.addGoldPrice(priceValue);
        System.out.println("================================================================" + "\n" + LachesismTools.getTime("yyyy年MM月dd日 HH时mm分ss秒") + "-  金价保存完毕" + "\n");

    }

    public void getDailyVideo() {
        System.out.println("================================================================" + "\n" + LachesismTools.getTime("yyyy年MM月dd日 HH时mm分ss秒") + "- 开始获取每日视频" + "\n");
        List<String> videoList = getVideoByApi();
        yunOMapper.addDailyVideo(videoList);
        System.out.println("================================================================" + "\n" + LachesismTools.getTime("yyyy年MM月dd日 HH时mm分ss秒") + "视频保存完毕" + "\n");

    }

    public void clearTempFiles() {
        String directoryPath = temp;
        File directory = new File(directoryPath);
        // 检查目录是否存在
        if (directory.exists() && directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    // 检查是否为文件
                    if (file.isFile()) {
                        try {
                            // 删除文件
                            Files.deleteIfExists(file.toPath());
                        } catch (IOException e) {
                            System.err.println("文件删除失败: " + file.getName() + " - " + e.getMessage());
                        }
                    }
                }
            }
        }
    }


    @SneakyThrows
    private String getNewGoldPrice() {
        String result = LachesismTools.sendGet("http://web.juhe.cn/finance/gold/shgold?v=&key=db0fda2e41742656c1fbe4502db3a488", null, null);
        JSONObject jsonObject = JSON.parseObject(result);
        JSONArray dataArray = jsonObject.getJSONArray("result");
        JSONObject resultList = (JSONObject) dataArray.get(0);
        JSONObject Au99 = resultList.getJSONObject("4");
        return Au99.getString("latestpri");
    }

    @SneakyThrows
    private List<String> getVideoByApi() {
        List<String> videoList = new ArrayList<String>();
        for (int i = 0; i < 100; i++) {
            String result = LachesismTools.sendGet("https://api.kuleu.com/api/MP4_xiaojiejie?type=json", null, null);
            String result2 = LachesismTools.sendGet("https://api.kuleu.com/api/xjj?type=json", null, null);
            JSONObject jsonObject = JSON.parseObject(result);
            JSONObject jsonObject2 = JSON.parseObject(result2);
            String mp4VideoUrl = jsonObject.getString("mp4_video");
            String video = jsonObject2.getString("video");
            videoList.add(mp4VideoUrl);
            videoList.add(video);
        }
        return videoList;
    }

    @SneakyThrows
    private void addOldCalendar() {
        System.out.println("================================================================" + "\n" + LachesismTools.getTime("yyyy年MM月dd日 HH时mm分ss秒") + "- 开始执行添加老黄历" + "\n");
        Map<String, String> map = new HashMap<>();
        map.put("date", getTomorrowTime(DATE_FORMATTER));
        map.put("key", "413bf77b8d10151af25495b7a2d13334");
        Map<String, String> map2 = new HashMap<>();
        map2.put("date", getTomorrowTime(DATE_FORMATTER));
        map2.put("key", "5a35d037b989665417ccd2ea8f63c59a");
        String result = LachesismTools.sendPost("https://apis.tianapi.com/lunar/index", map, null);
        String result2 = LachesismTools.sendGet("http://v.juhe.cn/laohuangli/d", map2, null);
        JSONObject resultObject = JSON.parseObject(result);
        JSONObject resultObject2 = JSON.parseObject(result2);
        ExtLunar extLunar = new ExtLunar();
        extLunar.setGregoriandate(resultObject.getJSONObject("result").getString("gregoriandate"));
        extLunar.setLunardate(resultObject2.getJSONObject("result").getString("yinli"));
        extLunar.setLunarFestival(resultObject.getJSONObject("result").getString("lunar_festival"));
        extLunar.setFestival(resultObject.getJSONObject("result").getString("festival"));
        extLunar.setFitness(resultObject.getJSONObject("result").getString("fitness"));
        extLunar.setTaboo(resultObject.getJSONObject("result").getString("taboo"));
        extLunar.setShenwei(resultObject.getJSONObject("result").getString("shenwei"));
        extLunar.setTaishen(resultObject.getJSONObject("result").getString("taishen"));
        extLunar.setChongsha(resultObject.getJSONObject("result").getString("chongsha"));
        extLunar.setSuisha(resultObject.getJSONObject("result").getString("suisha"));
        extLunar.setBaiji(resultObject2.getJSONObject("result").getString("baiji"));
        extLunar.setWuxing(resultObject2.getJSONObject("result").getString("wuxing"));
        extLunar.setWuxingjiazi(resultObject.getJSONObject("result").getString("wuxingjiazi"));
        extLunar.setWuxingnayear(resultObject.getJSONObject("result").getString("wuxingnayear"));
        extLunar.setWuxingnamonth(resultObject.getJSONObject("result").getString("wuxingnamonth"));
        extLunar.setXingsu(resultObject.getJSONObject("result").getString("xingsu"));
        extLunar.setPengzu(resultObject.getJSONObject("result").getString("pengzu"));
        extLunar.setJianshen(resultObject.getJSONObject("result").getString("jianshen"));
        extLunar.setTiangandizhiyear(resultObject.getJSONObject("result").getString("tiangandizhiyear"));
        extLunar.setTiangandizhimonth(resultObject.getJSONObject("result").getString("tiangandizhimonth"));
        extLunar.setTiangandizhiday(resultObject.getJSONObject("result").getString("tiangandizhiday"));
        extLunar.setLmonthname(resultObject.getJSONObject("result").getString("lmonthname"));
        extLunar.setShengxiao(resultObject.getJSONObject("result").getString("shengxiao"));
        extLunar.setLubarmonth(resultObject.getJSONObject("result").getString("lubarmonth"));
        extLunar.setLunarday(resultObject.getJSONObject("result").getString("lunarday"));
        extLunar.setJieqi(resultObject.getJSONObject("result").getString("jieqi"));
        String imgUrl = "https://yunlang-bid-document-dev.oss-cn-shanghai.aliyuncs.com/image/lunar/html/" + getTomorrowTime(DATE_FORMATTER) + ".png";
        imgUrl = LachesismTools.encrypt(imgUrl);
        extLunar.setImgUrl(imgUrl);
        yunOMapper.addOldCalendar(extLunar);
        System.out.println("================================================================" + "\n" + LachesismTools.getTime("yyyy年MM月dd日 HH时mm分ss秒") + "- 老黄历添加结束" + "\n");

    }

    @SneakyThrows
    private void getConstellationList() {
        System.out.println("================================================================" + "\n" + LachesismTools.getTime("yyyy年MM月dd日 HH时mm分ss秒") + "- 开始执行添加星座信息" + "\n");
        List<String> constellationName = new ArrayList<>();
        constellationName.add("水瓶座");
        constellationName.add("双鱼座");
        constellationName.add("白羊座");
        constellationName.add("金牛座");
        constellationName.add("双子座");
        constellationName.add("巨蟹座");
        constellationName.add("狮子座");
        constellationName.add("处女座");
        constellationName.add("天秤座");
        constellationName.add("天蝎座");
        constellationName.add("射手座");
        constellationName.add("摩羯座");
        List<ConstellationVO> todayConstellationList = new ArrayList<>();
        List<ConstellationVO> tomorrowConstellationList = new ArrayList<>();
        Map<String, String> map = new HashMap<>();
        map.put("key", "57cba589756c1028baffda9194d47cf6");
        map.put("type", "today");
        for (int i = 0; i < 12; i++) {
            map.put("consName", constellationName.get(i));
            ConstellationVO todayConstellationVO = new ConstellationVO();
            String todayResult = LachesismTools.sendGet("http://web.juhe.cn/constellation/getAll", map, null);
            JSONObject todayObject = JSON.parseObject(todayResult);
            todayConstellationVO.setConstellation(todayObject.getString("name"));
            todayConstellationVO.setQFriend(todayObject.getString("QFriend"));
            todayConstellationVO.setAll(todayObject.getString("all"));
            todayConstellationVO.setColor(todayObject.getString("color"));
            todayConstellationVO.setDate(todayObject.getString("datetime"));
            todayConstellationVO.setHealth(todayObject.getString("health"));
            todayConstellationVO.setLove(todayObject.getString("love"));
            todayConstellationVO.setMoney(todayObject.getString("money"));
            todayConstellationVO.setNumber(todayObject.getString("number"));
            todayConstellationVO.setSummary(todayObject.getString("summary"));
            todayConstellationVO.setWork(todayObject.getString("work"));
            todayConstellationVO.setType(1);
            todayConstellationList.add(todayConstellationVO);
        }
        yunOMapper.addConstellationList(todayConstellationList);
        todayConstellationList.clear();
        map.put("type", "tomorrow");
        for (int i = 0; i < 12; i++) {
            map.put("consName", constellationName.get(i));
            ConstellationVO tomorrowConstellationVO = new ConstellationVO();
            String todayResult = LachesismTools.sendGet("http://web.juhe.cn/constellation/getAll", map, null);
            JSONObject todayObject = JSON.parseObject(todayResult);
            tomorrowConstellationVO.setConstellation(todayObject.getString("name"));
            tomorrowConstellationVO.setQFriend(todayObject.getString("QFriend"));
            tomorrowConstellationVO.setAll(todayObject.getString("all"));
            tomorrowConstellationVO.setColor(todayObject.getString("color"));
            tomorrowConstellationVO.setDate(todayObject.getString("datetime"));
            tomorrowConstellationVO.setHealth(todayObject.getString("health"));
            tomorrowConstellationVO.setLove(todayObject.getString("love"));
            tomorrowConstellationVO.setMoney(todayObject.getString("money"));
            tomorrowConstellationVO.setNumber(todayObject.getString("number"));
            tomorrowConstellationVO.setSummary(todayObject.getString("summary"));
            tomorrowConstellationVO.setWork(todayObject.getString("work"));
            tomorrowConstellationVO.setType(2);
            tomorrowConstellationList.add(tomorrowConstellationVO);
        }
        yunOMapper.addConstellationList(tomorrowConstellationList);
        tomorrowConstellationList.clear();
        List<ConstellationVO> weekConstellationList = new ArrayList<>();
        map.put("type", "week");
        for (int i = 0; i < 12; i++) {
            map.put("consName", constellationName.get(i));
            ConstellationVO weekConstellationVO = new ConstellationVO();
            String todayResult = LachesismTools.sendGet("http://web.juhe.cn/constellation/getAll", map, null);
            JSONObject todayObject = JSON.parseObject(todayResult);
            weekConstellationVO.setConstellation(todayObject.getString("name"));
            weekConstellationVO.setWeekth(todayObject.getInteger("weekth"));
            weekConstellationVO.setDate(todayObject.getString("date"));
            weekConstellationVO.setHealth(todayObject.getString("health"));
            weekConstellationVO.setLove(todayObject.getString("love"));
            weekConstellationVO.setMoney(todayObject.getString("money"));
            weekConstellationVO.setWork(todayObject.getString("work"));
            weekConstellationVO.setType(3);
            weekConstellationList.add(weekConstellationVO);
        }
        yunOMapper.addConstellationList(weekConstellationList);
        weekConstellationList.clear();
        List<ConstellationVO> monthConstellationList = new ArrayList<>();
        map.put("key", "b7ba619796b830b3407220e57d2448ad");
        map.put("type", "month");
        for (int i = 0; i < 12; i++) {
            map.put("consName", constellationName.get(i));
            ConstellationVO monthConstellationVO = new ConstellationVO();
            String todayResult = LachesismTools.sendGet("http://web.juhe.cn/constellation/getAll", map, null);
            JSONObject todayObject = JSON.parseObject(todayResult);
            monthConstellationVO.setConstellation(todayObject.getString("name"));
            monthConstellationVO.setDate(todayObject.getString("date"));
            monthConstellationVO.setAll(todayObject.getString("all"));
            monthConstellationVO.setHealth(todayObject.getString("health"));
            monthConstellationVO.setLove(todayObject.getString("love"));
            monthConstellationVO.setMoney(todayObject.getString("money"));
            monthConstellationVO.setWork(todayObject.getString("work"));
            monthConstellationVO.setType(4);
            monthConstellationList.add(monthConstellationVO);
        }
        yunOMapper.addConstellationList(monthConstellationList);
        monthConstellationList.clear();
        List<ConstellationVO> yearConstellationList = new ArrayList<>();
        map.put("key", "57cba589756c1028baffda9194d47cf6");
        map.put("type", "year");
        for (int i = 0; i < 12; i++) {
            map.put("consName", constellationName.get(i));
            ConstellationVO yearConstellationVO = new ConstellationVO();
            String todayResult = LachesismTools.sendGet("http://web.juhe.cn/constellation/getAll", map, null);
            JSONObject todayObject = JSON.parseObject(todayResult);
            yearConstellationVO.setConstellation(todayObject.getString("name"));
            yearConstellationVO.setDate(todayObject.getString("date"));
            String work = (String) todayObject.getJSONArray("career").get(0);
            String love = (String) todayObject.getJSONArray("love").get(0);
            String health = (String) todayObject.getJSONArray("health").get(0);
            String money = (String) todayObject.getJSONArray("finance").get(0);
            String all = JSON.parseObject(todayObject.getString("mima")).getString("info");
            String summary = JSON.parseObject(todayObject.getString("mima")).getString("text");
            yearConstellationVO.setWork(work);
            yearConstellationVO.setLove(love);
            yearConstellationVO.setHealth(health);
            yearConstellationVO.setMoney(money);
            yearConstellationVO.setAll(all);
            yearConstellationVO.setSummary(summary);
            yearConstellationVO.setType(5);
            yearConstellationList.add(yearConstellationVO);
        }
        yunOMapper.addConstellationList(yearConstellationList);
        yearConstellationList.clear();
        System.out.println("================================================================" + "\n" + LachesismTools.getTime("yyyy年MM月dd日 HH时mm分ss秒") + "- 结束星座添加" + "\n");
    }


    @Override
    public List<String> getEat() {
        return yunOMapper.getEat();
    }

    @Override
    public List<GoldPrice> getGoldPriceToday(GoldPrice time) {
        return yunOMapper.getGoldPriceToday(time);
    }

    @Override
    public List<GoldPrice> getGoldPriceHistory(GoldPrice time) {
        return yunOMapper.getGoldPriceHistory(time);
    }

    @Override
    public BigDecimal getLastPrice(GoldPrice time) {
        return yunOMapper.getLastPrice(time);
    }


    @Override
    public String getGoldPrice() throws IOException {
        String cachePrice = (String) redisService.getWithTimeout("goldPrice");
        if (cachePrice != null) {
            return cachePrice;
        }
        String result = LachesismTools.sendGet("http://web.juhe.cn/finance/gold/shgold?v=&key=db0fda2e41742656c1fbe4502db3a488", null, null);
        JSONObject jsonObject = JSON.parseObject(result);
        JSONArray dataArray = jsonObject.getJSONArray("result");
        JSONObject resultList = (JSONObject) dataArray.get(0);
        JSONObject Au99 = resultList.getJSONObject("4");
        String price = Au99.getString("latestpri");
        redisService.set("goldPrice", price, 1);
        return price;
    }

    @Override
    public String getAreaCode(String city, String area) {
        return yunOMapper.getAreaCode(city, area);
    }

    @Override
    public void addAreaCode(String city, String area, String code) {
        yunOMapper.addAreaCode(city, area, code);
    }

    @Override
    public List<WeatherVO> getWeather(String code) {
        return (List<WeatherVO>) redisService.getWithTimeout(code);
    }

    @Override
    public void addWeather(CityWeatherVO cityWeatherInfo) {
        redisService.set(cityWeatherInfo.getCode(), cityWeatherInfo.getFurtherWeather(), 2);
    }

    @Override
    public ResponsePage<ToDoS> getToDoList(ToDoS todos) {
        PageHelper.startPage(todos.getPageNum(), 10);
        List<ToDoS> todoList = yunOMapper.getToDoList(todos);
        return ResponsePage.restPage(new PageInfo<>(todoList));
    }

    @Override
    public void updateToDos(ToDoS todos) {
        if (todos.getStatus() != null && todos.getStatus().equals(1)) {
            todos.setFinishTime(new Date());
        }

        yunOMapper.updateToDos(todos);
    }

    @Override
    public void createToDoThing(ToDoS todos) {
        yunOMapper.createToDoThing(todos);
    }


    @Override
    public ResponsePage<StringInfoVO> getFamilyMotto(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<StringInfoVO> motttoList = yunOMapper.getFamilyMotto();
        return ResponsePage.restPage(new PageInfo<>(motttoList));
    }

    @Override
    public List<String> getCatalogInfo() {
        List<String> info = new ArrayList<>();
        try {
            File directory = new File("/project/media/icon/");
            File[] files = directory.listFiles();
            for (File file : files) {
                info.add("https://www.yunox.cn/icon/" + file.getName());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return info;
    }

    @Override
    public ResponsePage<MessageVO> getMessageList(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<MessageVO> messageList = yunOMapper.getMessageList();
        return ResponsePage.restPage(new PageInfo<>(messageList));
    }

    @Override
    public Answer getAnswer() {
        Random random = new Random(); // 创建Random对象
        int randomNumber = 1 + random.nextInt(274);
        return yunOMapper.getAnswer(randomNumber);
    }

    @Override
    public ResponsePage<AnimatedCharacters> getAnimatedCharacterList(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<AnimatedCharacters> animatedCharactersList = yunOMapper.getAnimatedCharacterList();
        return ResponsePage.restPage(new PageInfo<>(animatedCharactersList));
    }


    @Override
    public List<String> getConstellation(ConstellationParam constellationParam) {
        int birthYear = constellationParam.getYear();
        int birthMonth = constellationParam.getMonth();
        int birthDay = constellationParam.getDay();
        int hour = constellationParam.getHour();
        int minute = constellationParam.getMinute();
        List<String> constellationInfo = new LinkedList<>();
        double julianDate = calculateJulianDate(birthYear, birthMonth, birthDay);
        String moonSign = estimateMoonSign(birthYear, birthMonth, birthDay);
        String zodiacSigns = getZodiacSign(birthMonth, birthDay);
        String ascendant = calculateAscendant(birthMonth, birthDay, hour, minute);
        int index = 0;
        for (int i = 0; i < ZODIAC_SIGNS.length; i++) {
            if (ZODIAC_SIGNS[i].equals(ascendant)) {
                index = i;
                break;
            }
        }
        constellationInfo.add("宫主星：" + ZODIAC_SIGNS[index]);
        for (int i = 1; i <= 12; i++) {
            int houseIndex = (index + i) % 12;
            constellationInfo.add("第" + i + "宫：" + ZODIAC_SIGNS[houseIndex]);
        }
        Map<String, Double> stringDoubleMap = calculatePlanetPosition(julianDate);
        constellationInfo.add("太阳星座是: " + zodiacSigns);
        constellationInfo.add("月亮星座是: " + moonSign);
        constellationInfo.add("上升星座是: " + ascendant);
        constellationInfo.add(birthYear + "年" + birthMonth + "月" + birthDay + "日的 '儒略日' : " + julianDate);
        constellationInfo.add("当天地球位置: " + stringDoubleMap.get("earthPosition") + " AU");
        constellationInfo.add("当天火星位置: " + stringDoubleMap.get("marsPosition") + " AU");
        constellationInfo.add("当天金星位置: " + stringDoubleMap.get("venusPosition") + " AU");
        constellationInfo.add("当天水星位置: " + stringDoubleMap.get("mercuryPosition") + " AU");
        constellationInfo.add("当天木星位置: " + stringDoubleMap.get("jupiterPosition") + " AU");
        constellationInfo.add("当天月亮位置: " + stringDoubleMap.get("moonPosition") + " AU");
        constellationInfo.add("当天土星位置: " + stringDoubleMap.get("saturnPosition") + " AU");
        constellationInfo.add("当天天王星位置: " + stringDoubleMap.get("uranusPosition") + " AU");
        constellationInfo.add("当天海王位置: " + stringDoubleMap.get("neptunePosition") + " AU");
        constellationInfo.add("当天冥王星位置: " + stringDoubleMap.get("plutoPosition") + " AU");
        constellationInfo.add("(AU是天文单位（Astronomical Unit）的缩写，它是用于测量天体之间距离的一种单位。1 AU 定义地球与太阳之间的平均距离，大约等于149,597,870.7公里（约92,955,807英里）。这个距离被用作一个标准，用来描述太阳系内其他行星与太阳之间的距离，以及行星之间的相对距离。)");
        return constellationInfo;
    }

    @Override
    public void addNote(NoteVO note) {
        yunOMapper.addNote(note);
    }

    @Override
    public NoteVO getNote(String code) {
        return yunOMapper.getNote(code);
    }

    @Override
    public Boolean checkRepeatCode(NoteVO note) {
        Integer bool = yunOMapper.checkRepeatCode(note);
        return bool <= 0;
    }


    @Override
    public String uploadFile(MultipartFile file, String code) {
        // 检查文件是否为空
        if (file.isEmpty()) {
            throw new RuntimeException("文件为空");
        }

        // 获取原始文件名
        String originalFileName = file.getOriginalFilename();
        String newFileName = LachesismTools.getTime("ddHHmm") + "_" + originalFileName;
        if (originalFileName != null && originalFileName.length() > 12 && originalFileName.contains(".")) {
            String type = originalFileName.substring(originalFileName.lastIndexOf('.'));
            newFileName = LachesismTools.getTime("ddHHmm") + type;
        }
        // 构造保存文件的完整路径
        String saveDir = "/project/media/file/"; // 确保这个路径在服务器上是存在的
        Path targetLocation = Paths.get(saveDir + newFileName);
        try {
            // 将上传的文件保存到指定路径
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            // 如果保存文件失败，抛出异常
            throw new RuntimeException("保存文件失败：" + e.getMessage());
        }
        // 将文件 URL 和 code 存储到数据库
        String fileUrl = "https://www.yunox.cn/files/" + newFileName;
        yunOMapper.addFileLog(fileUrl, code);
        return fileUrl;
    }

    @Override
    public String uploadTempFile(MultipartFile file) {
        if (file.isEmpty()) {
            throw new RuntimeException("文件为空");
        }
        String fileName = file.getOriginalFilename();
        String newFileName = LachesismTools.generateRandomCode(10);
        if (fileName != null && fileName.contains(".")) {
            String type = fileName.substring(fileName.lastIndexOf('.'));
            newFileName = newFileName + type;
        }
        Path targetLocation = Paths.get(temp, newFileName); // 使用 Paths.get 组合路径
        try {
            // 确保保存目录存在，如果不存在则创建
            Files.createDirectories(targetLocation.getParent());
            // 将上传的文件保存到指定路径
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            // 如果保存文件失败，抛出异常
            throw new RuntimeException("保存文件失败：" + e.getMessage());
        }
        return newFileName;
    }

    @Override
    public List<Word> getHousekeepingWiki(StringInfoVO keyWord) {
        return yunOMapper.getHousekeepingWiki(keyWord);
    }

    @Override
    public void addHousekeepingWiki(Word word) {
        yunOMapper.addHousekeepingWiki(word);
    }

    @Override
    public void addMemorandum(MemorandumVO memorandum) {
        yunOMapper.addMemorandum(memorandum);
    }

    @Override
    public void updateMemorandum(MemorandumVO memorandum) {
        yunOMapper.updateMemorandum(memorandum);
    }

    @Override
    public List<MemorandumVO> getMemorandum(MemorandumVO memorandum) {
        return yunOMapper.getMemorandum(memorandum);
    }

    @Override
    public List<String> getDailyVideoList() {
        return yunOMapper.getDailyVideoList();
    }

    @Override
    public List<SysArea> getAreaList() {
        List<SysArea> areaList = (List<SysArea>) redisService.getWithTimeout(AREA_LIST_CACHE);
        if (areaList == null) {
            areaList = new ArrayList<>();
            // 缓存中没有数据，查询数据库
            areaList = yunOMapper.getAreaList();

            // 按levelType分组并且同时以districtId作为键建立区域映射
            Map<Integer, List<SysArea>> levelTypeMap = areaList.stream()
                    .collect(Collectors.groupingBy(SysArea::getLevelType));

            // 使用一个Map来存储每个区域的ID与区域的映射
            Map<Integer, SysArea> areaMap = areaList.stream()
                    .collect(Collectors.toMap(SysArea::getDistrictId, area -> area));

            // 存储最终的结果，按levelType层级来存储区域
            List<SysArea> resultList = new ArrayList<>();

            // 获取不同层级的区域
            List<SysArea> sysAreas = levelTypeMap.get(0);  // 根区域（通常为国家）
            List<SysArea> provinceList = levelTypeMap.get(1);  // 省级区域
            List<SysArea> cityList = levelTypeMap.get(2);  // 市级区域
            List<SysArea> districtList = levelTypeMap.get(3);  // 区县级区域

            // 组装区域层级结构
            if (sysAreas != null) {
                for (SysArea sysArea : sysAreas) {
                    // 直接查找省级区域并建立子父关系
                    sysArea.setSonList(getChildren(provinceList, sysArea.getDistrictId(), areaMap)
                            .stream()
                            .peek(province -> {
                                // 对每个省级区域，查找市级区域并建立子父关系
                                province.setSonList(getChildren(cityList, province.getDistrictId(), areaMap)
                                        .stream()
                                        .peek(city -> {
                                            // 对每个市级区域，查找区县级区域并建立子父关系
                                            city.setSonList(getChildren(districtList, city.getDistrictId(), areaMap));
                                        })
                                        .collect(Collectors.toList()));
                            })
                            .collect(Collectors.toList()));
                    resultList.add(sysArea);  // 将根区域添加到最终结果
                }
            }
            // 将查询结果存入缓存
            redisService.set(AREA_LIST_CACHE, resultList);
            return resultList;
        }
        // 如果缓存中有数据，直接返回
        return areaList;
    }

    @Override
    public List<ConstellationDTO> getConstellationFortune() {
        List<ConstellationDTO> constellationDTOList = (List<ConstellationDTO>) redisService.getWithTimeout(CONSTELLATION_LIST_CACHE);
        if (constellationDTOList == null || constellationDTOList.isEmpty()) {
            constellationDTOList = new ArrayList<>();
            List<ConstellationVO> constellationList = yunOMapper.getConstellationFortuneList();
            if (constellationList.isEmpty()) {
                getConstellationList();
            }
            Map<String, List<ConstellationVO>> groupedByConstellation = constellationList.stream()
                    .collect(Collectors.groupingBy(ConstellationVO::getConstellation));
            for (Map.Entry<String, List<ConstellationVO>> entry : groupedByConstellation.entrySet()) {
                ConstellationDTO constellationDTO = new ConstellationDTO();
                constellationDTO.setConstellation(entry.getKey());
                List<ConstellationVO> fortuneList = entry.getValue();
                for (ConstellationVO constellationVO : fortuneList) {
                    switch (constellationVO.getType()) {
                        case CONSTELLATION_FORTUNE_TODAY:
                            constellationDTO.setToday(constellationVO);
                            break;
                        case CONSTELLATION_FORTUNE_TOMORROW:
                            constellationDTO.setTomorrow(constellationVO);
                            break;
                        case CONSTELLATION_FORTUNE_WEEK:
                            constellationDTO.setWeek(constellationVO);
                            break;
                        case CONSTELLATION_FORTUNE_MONTH:
                            constellationDTO.setMouth(constellationVO);
                            break;
                        case CONSTELLATION_FORTUNE_YEAR:
                            constellationDTO.setYear(constellationVO);
                            break;
                        default:
                            break;
                    }
                }
                constellationDTOList.add(constellationDTO);
            }
        }
        redisService.set(CONSTELLATION_LIST_CACHE, constellationDTOList, getSecondsUntilMidnight() + 3600, TimeUnit.SECONDS);
        return constellationDTOList;
    }

    @Override
    public ExtLunar getLunarInfo() {
        ExtLunar lunarInfo = (ExtLunar) redisService.getWithTimeout(LUNAR_CACHE);
        if (lunarInfo == null) {
            lunarInfo = yunOMapper.getLunarInfo();
            redisService.set(LUNAR_CACHE, lunarInfo, getSecondsUntilMidnight() + 3599, TimeUnit.SECONDS); // 60分钟更新一次
        }
        return lunarInfo;

    }

    @Override
    public ResponsePage<SysSuggestions> getSuggestionList(Integer pageNum) {
        PageHelper.startPage(pageNum, 30);
        List<SysSuggestions> suggestions = yunOMapper.getSuggestionList();
        return ResponsePage.restPage(new PageInfo<>(suggestions));
    }

    @Override
    public void addSuggestion(SysSuggestions suggestion) {
        yunOMapper.addSuggestion(suggestion);
    }

    public static int getDayIndex() {
        // 基准日
        LocalDate baseDate = LocalDate.of(2025, 5, 26);
        // 当前日期
        LocalDate today = LocalDate.now();

        long daysBetween = ChronoUnit.DAYS.between(baseDate, today);

        // 如果今天是基准日，daysBetween 为 0，需要 +1
        if (daysBetween >= 0) {
            return (int) daysBetween + 1;
        } else {
            // 也可以根据需要抛出异常或返回0
            return 0;
        }
    }

    @Override
    public void addEat(String food) {
        // 获取完整日期（格式：yyyy-MM-dd 星期几）
        String fullDate = getTime("yyyy-MM-dd E");
        // 获取当前时间（格式：HH:mm）
        String time = getTime("HH:mm");
        // 获取当前小时（整型）
        int hour = Integer.parseInt(getTime("HH"));

        // 判断当前时间属于早（0），中（1），晚（2）
        int timeIndex;
        if (hour < 11) {
            timeIndex = 0; // 早
        } else if (hour < 16) {
            timeIndex = 1; // 中
        } else {
            timeIndex = 2; // 晚
        }
        // 拼接最终要写入的内容：时间 + 空格 + 食物名称
        String finalFood = time + "   " + food;
        // 交给异步处理
        AsyncUtil.executeAsync(() -> writeFoodToExcel(finalFood, timeIndex, fileAddress+"/每天吃什么.xlsx"));
        AsyncUtil.executeAsync(() -> writeFoodToExcel(food, timeIndex, fileAddress+"/每天吃什么2.xlsx"));
    }

    private void writeFoodToExcel(String food, int timeIndex, String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            System.err.println("❌ 文件不存在：" + filePath);
            return;
        }

        try (
                FileInputStream fis = new FileInputStream(file);
                Workbook workbook = new XSSFWorkbook(fis)
        ) {
            Sheet sheet = workbook.getSheetAt(0);
            int dayIndex = getDayIndex();
            int quotient = dayIndex / 14;
            int remainder = dayIndex % 14;
            int dateIndex = quotient * 6 + 2;
            int rowIndex = dateIndex + timeIndex;
            int dateRow = (remainder > 7) ? remainder + 3 : remainder;

            Row row = sheet.getRow(rowIndex);
            if (row == null) row = sheet.createRow(rowIndex);
            Cell cell = row.getCell(dateRow);
            if (cell == null) cell = row.createCell(dateRow);

            String existing = "";
            if (cell.getCellType() == CellType.STRING) {
                existing = cell.getStringCellValue();
            }

            cell.setCellValue(existing.isEmpty() ? food : existing + "\n" + food);

            CellStyle oldStyle = cell.getCellStyle();
            CellStyle newStyle = workbook.createCellStyle();
            newStyle.cloneStyleFrom(oldStyle);
            newStyle.setWrapText(true);
            newStyle.setAlignment(HorizontalAlignment.CENTER);
            newStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            cell.setCellStyle(newStyle);

            try (FileOutputStream fos = new FileOutputStream(file)) {
                workbook.write(fos);
            }

            System.out.println("✅ 写入成功：" + getTime("yyyy-MM-dd E") + " -> " + food);

        } catch (Exception e) {
            System.err.println("❌ 写入 Excel 出错：" + filePath);
            e.printStackTrace();
        }
    }


    // 获取给定父区域id的所有子区域
    private List<SysArea> getChildren(List<SysArea> areaList, Integer parentId, Map<Integer, SysArea> areaMap) {
        return areaList.stream()
                .filter(area -> area.getParentId().equals(parentId))
                .collect(Collectors.toList());
    }


    @Override
    public void scanUpload(MultipartFile file, String sessionId) {
        if (file.isEmpty()) {
            throw new RuntimeException("文件为空");
        }
        // 获取原始文件名
        String fileName = file.getOriginalFilename();
        String saveDir = temp + sessionId + "/"; // 确保这个路径在服务器上是存在的
        Path targetLocation = Paths.get(saveDir, fileName); // 使用 Paths.get 组合路径
        try {
            // 确保保存目录存在，如果不存在则创建
            Files.createDirectories(targetLocation.getParent());
            // 将上传的文件保存到指定路径
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
            System.out.println("成功");
        } catch (IOException e) {
            // 如果保存文件失败，抛出异常
            throw new RuntimeException("保存文件失败：" + e.getMessage());
        }
    }


    @Override
    public String getFilePath(String code) {
        return yunOMapper.getFilePathByCode(code);
    }

    @Override
    public List<NoteVO> getDBFileInfo(Integer type) {
        if (type == null) {
            return Collections.emptyList(); // 或者根据实际情况处理
        }
        switch (type) {
            case 1:
                return yunOMapper.getFileLogInfo();
            case 2:
                return yunOMapper.getNoteLogInfo();
            default:
                return Collections.emptyList(); // 返回空列表而不是null
        }
    }

    @Override
    public void deleteDBFile(Integer type, Integer id) {
        switch (type) {
            case 1:
                yunOMapper.deleteDFile(id);
                break;
            case 2:
                yunOMapper.deleteDNote(id);
                break;
            default:
                break;
        }
    }

    @Override
    public List<Bill> getBillList(Bill bill) {
        return yunOMapper.getBillList(bill);
    }

    @Override
    public void updateBill(Bill bill) {
        yunOMapper.updateBill(bill);
    }

    @Override
    public Integer addBill(Bill bill) {
        yunOMapper.addBill(bill);
        return bill.getId();
    }

    @Override
    public List<Pasteboard> getPasteboardList(Pasteboard pasteboard) {
        return yunOMapper.getPasteboardList(pasteboard);
    }

    @Override
    public void deletePasteboard(Integer id) {
        yunOMapper.updatePasteboard(id);
    }

    @Override
    public Integer addPasteboard(Pasteboard pasteboard) {
        yunOMapper.addPasteboard(pasteboard);
        return pasteboard.getId();
    }

    @Override
    public List<StringInfoVO> getRandomCriminalLaws(Integer type) {
        List<StringInfoVO> randomCriminalLaws = yunOMapper.getRandomCriminalLaws(type);
        return randomCriminalLaws.stream()
                .sorted(Comparator.comparingInt(StringInfoVO::getId))
                .collect(Collectors.toList());
    }

    @Override
    public List<StringInfoVO> fuzzyGetCriminalLaw(StringInfoVO keyWord) {
        return yunOMapper.fuzzyGetCriminalLaw(keyWord.getInfo(), keyWord.getId());
    }

    @Override
    public List<Word> getWords() {
        return yunOMapper.getWords();
    }

    @Override
    public List<Word> getWordByKeyword(Word word) {
        return yunOMapper.getWordByKeyword(word);
    }


}
